package java_thinking.unit_14._14_7_Proxy;

/**
 * @Description :   静态代理结构实例
 *
 *                  在任何时刻，只要你想将额外的操作从“实际”对象中分离到不同的地方，特别是你希望能够很容易的
 *                  做出修改，从没有使用额外操作转为使用这些操作，或者反过来时，代理就显得很有用(设计模式的关键
 *                  就是封装和修改---因此你需要修改事务以证明这种模式的正确性)；
 *
 *                  例如。如果你希望跟踪对RealObject中方法调用，或者希望度量这些调用的开销，那么应该如何做呢，
 *                  这些代码肯定不希望将其合并到应用中的代码，因此代理使得你可以很容易的添加或移除他们；
 *
 *                  静态代理的实现模式：
 *
 *                  1. 首先创建一个接口（JDK代理都是面向接口的），
 *
 *                  2. 创建具体实现类来实现这个接口，
 *
 *                  3. 创建一个代理类同样实现这个接口，不同之处在于具体实现类的方法中需要将接口中定义的方法的业务
 *                  逻辑功能实现，而代理类中的方法只要调用具体类中的对应方法即可，这样我们在需要使用接口中的某个方
 *                  法的功能时直接调用代理类的方法即可，将具体的实现类隐藏在底层。
 *
 *                  静态代理类优缺点
 *                  优点：业务类只需要关注业务逻辑本身，保证了业务类的重用性。这是代理的共有优点。
 *                  缺点：
 *                  1）代理对象的一个接口只服务于一种类型的对象，如果要代理的方法很多，势必要为每一种方法都进行代
 *                  理，静态代理在程序规模稍大时就无法胜任了。
 *                  2）如果接口增加一个方法，除了所有实现类需要实现这个方法外，所有代理类也需要实现此方法。增加了
 *                  代码维护的复杂度。
 *                  如果要按照上述的方法使用代理模式，那么真实角色(委托类)必须是事先已经存在的，并将其作为代理对象
 *                  的内部属性。但是实际使用时，一个真实角色必须对应一个代理角色，如果大量使用会导致类的急剧膨胀；
 *                  此外，如果事先并不知道真实角色（委托类），该如何使用代理呢？这个问题可以通过Java的动态代理类来
 *                  解决。
 *
 *                  动态代理也有缺点：
 *                  一 是它的实现比静态代理更加复杂也不好理解；
 *                  二 是它存在一定的限制，例如它要求需要代理的对象必须实现了某个接口；
 *                  三 是它不够灵活，动态代理会为接口中的声明的所有方法添加上相同的代理逻辑。
 *
 *                  动态代理才真正的将代码中横向切面的逻辑剥离了出来
 *
 * @author: cww
 * @DateTime: 2019-03-31 10:23
 */
interface Interface{
    void doSomething();
    void somethingElse(String arg);
    void somethingElse1(String arg);
}
/**
 * @author asd730520@live.com
 */
class RealObject implements Interface {

    @Override
    public void doSomething() {
        System.out.println("RealObject doSomething ");
    }

    @Override
    public void somethingElse(String arg) {
        System.out.println("RealObject somethingElse arg: "+arg);
    }
    @Override
    public void somethingElse1(String arg) {
        System.out.println("RealObject somethingElse arg: "+arg);
    }
}

class ElseObject implements Interface{

    @Override
    public void doSomething() {
        System.out.println("ElseObject doSomething");
    }

    @Override
    public void somethingElse(String arg) {
        System.out.println("ElseObject somethingElse arg: "+arg);
    }
    @Override
    public void somethingElse1(String arg) {
        System.out.println("ElseObject somethingElse arg: "+arg);
    }
}
/**
 * 静态代理缺点，代理的接口改变，或者很多方法，那代理内部也要相应的实现代理方法，而动态代理就不需要了
 * @author asd730520@live.com
 */
public class SimpleProxy implements Interface {
    private Interface proxied;
    public SimpleProxy(Interface proxied){
        this.proxied = proxied;
    }
    @Override
    public void doSomething() {
        System.out.println("SimpleProxy doSomething proxied.class "+proxied.getClass().getSimpleName());
        proxied.doSomething();
    }

    @Override
    public void somethingElse(String arg) {
        System.out.println("SimpleProxy somethingElse proxied.class "+proxied.getClass().getSimpleName());
        proxied.somethingElse(arg);
    }
    @Override
    public void somethingElse1(String arg) {
        System.out.println("SimpleProxy somethingElse proxied.class "+proxied.getClass().getSimpleName());
        proxied.somethingElse(arg);
    }

}

class SimpleProxyDemo {
    public static void consumer(Interface iface) {
        iface.doSomething();
        iface.somethingElse("bo");
    }

    public static void main(String[] args) {
        consumer(new RealObject());
        consumer(new SimpleProxy(new RealObject()));
        consumer(new SimpleProxy(new ElseObject()));
    }
}
